import java.io.FileOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.io.*;
import java.util.Scanner;

public class Student implements Serializable {
    private static final long serialVersionUID = 1L;
    private int sno;
    private String sname;
    private String gender;
    private String nation;
    private int age;

    public Student(int sno, String sname, String gender, String nation, int age) {
        this.sno = sno;
        this.sname = sname;
        this.gender = gender;
        this.nation = nation;
        this.age = age;
    }

    public void setSno(int sno) {
        this.sno = sno;
    }

    public int getSno() {
        return sno;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSname() {
        return sname;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public String getGender() {
        return gender;
    }

    public void setNation(String nation) {
        this.nation = nation;
    }

    public String getNation() {
        return nation;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    public static void main(String[] args) {
        ArrayList<Student> arrayList = new ArrayList<>();
        LinkedList<Student> linkedList = new LinkedList<>();
        String filename = "Student.dat";

        menu(arrayList, linkedList, filename);

        writeFile(arrayList, linkedList, filename);
        readFile(arrayList, linkedList, filename);
    }

    public static void menu(ArrayList<Student> arrayList, LinkedList<Student> linkedList, String filename) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t学生数组操作软件");
            System.out.println("\t-------------------------------");
            System.out.println("\t\t 1--基本输入/输出");
            System.out.println("\t\t 2--数据统计");
            System.out.println("\t\t 3--数据排序");
            System.out.println("\t\t 4--数据查找");
            System.out.println("\t\t 5--删除操作");
            System.out.println("\t\t 6--插入操作");
            System.out.println("\t\t 7--对学生数组特殊处理");
            System.out.println("\t\t 0--退出");
            System.out.println("\t-------------------------------");
            System.out.print("\t\t请选择(0 - 7)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    menu1(arrayList, linkedList);
                    break;
                case 2:
                    menu2(arrayList, linkedList);
                    break;
                case 3:
                    menu3(arrayList, linkedList);
                    break;
                case 4:
                    menu4(arrayList, linkedList);
                    break;
                case 5:
                    menu5(arrayList, linkedList);
                    break;
                case 6:
                    menu6(arrayList, linkedList);
                    break;
                case 7:
                    menu7(arrayList, linkedList);
                    break;
                default:
                    continue;
            }
            System.out.println();
            System.out.print("\t\t按任意键继续...");
            scanner.nextLine(); // 消费换行符
            scanner.nextLine(); // 等待用户按任意键继续
        }
    }

    public static void menu1(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t  学生数据输入/输出");
            System.out.println("\t\t---------------------");
            System.out.println("\t\t  1--数据输入");
            System.out.println("\t\t  2--数据输出");
            System.out.println("\t\t  0--返回");
            System.out.println("\t\t---------------------");
            System.out.print("\t\t请选择(0 - 2)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    inputAll(arrayList, linkedList);
                    break;
                case 2:
                    outputAll(arrayList, linkedList);
                    break;
                default:
                    continue;
            }
        }
    }

    public static void menu2(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t  学生数据统计");
            System.out.println("\t\t--------------------------");
            System.out.println("\t\t  1--按性别计算学生人数");
            System.out.println("\t\t  2--计算平均年龄");
            System.out.println("\t\t  0--返回");
            System.out.println("\t\t--------------------------");
            System.out.print("\t\t请选择(0 - 2)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    System.out.print("\t\t输入性别：");
                    String gender = scanner.next();
                    int count = computeByGender(arrayList, linkedList, gender);
                    System.out.println("\t\t" + gender + "学生人数：" + count);
                    break;
                case 2:
                    float avgAge = computeAVG(arrayList, linkedList);
                    System.out.println("\t\t学生平均年龄：" + avgAge);
                    break;
                default:
                    continue;
            }
        }
    }

    public static void menu3(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t  学生数据排序");
            System.out.println("\t\t-------------------");
            System.out.println("\t\t  1--按年龄排序");
            System.out.println("\t\t  2--按民族排序");
            System.out.println("\t\t  0--返回");
            System.out.println("\t\t-------------------");
            System.out.print("\t\t请选择(0 - 2)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    sortByAge(arrayList, linkedList);
                    System.out.println("\t\t按年龄排序完成！");
                    break;
                case 2:
                    sortByNation(arrayList, linkedList);
                    System.out.println("\t\t按民族排序完成！");
                    break;
                default:
                    continue;
            }
        }
    }

    public static void menu4(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t  学生数据查找");
            System.out.println("\t\t---------------------");
            System.out.println("\t\t  1--按学号查找学生");
            System.out.println("\t\t  2--按姓名查找学生");
            System.out.println("\t\t  0--返回");
            System.out.println("\t\t---------------------");
            System.out.print("\t\t请选择(0 - 2)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    System.out.print("\t\t待查找学生学号：");
                    int varSno = scanner.nextInt();
                    int index = findBySno(arrayList, linkedList, varSno);
                    if (index == -1) {
                        System.out.println("\t\t查无此人(学号：" + varSno + ")，查找失败！");
                    } else {
                        output(arrayList.get(index));
                    }
                    break;
                case 2:
                    System.out.println("\t\t暂未实现按姓名查找功能！");
                    break;
                default:
                    continue;
            }
        }
    }

    public static void menu5(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t  删除学生操作");
            System.out.println("\t\t----------------------");
            System.out.println("\t\t  1--删除第1个元素");
            System.out.println("\t\t  2--删除最后元素");
            System.out.println("\t\t  3--按学号删除元素");
            System.out.println("\t\t  0--返回");
            System.out.println("\t\t----------------------");
            System.out.print("\t\t请选择(0 - 3)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    deletion(arrayList, linkedList, 0);
                    System.out.println("\t\t删除第1个元素完成！");
                    break;
                case 2:
                    deletion(arrayList, linkedList, arrayList.size() - 1);
                    System.out.println("\t\t删除最后元素完成！");
                    break;
                case 3:
                    System.out.print("\t\t待删除学生学号：");
                    int varSno = scanner.nextInt();
                    int result = deleteBySno(arrayList, linkedList, varSno);
                    if (result == -1) {
                        System.out.println("\t\t查无此人(学号：" + varSno + ")，删除失败！");
                    } else {
                        System.out.println("\t\t成功删除(学号：" + varSno + ")");
                    }
                    break;
                default:
                    continue;
            }
        }
    }

    public static void menu6(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        while (true) {
            System.out.println("\n\t\t  插入学生操作");
            System.out.println("\t\t-------------------------------");
            System.out.println("\t\t  1--插入到第1个元素处");
            System.out.println("\t\t  2--插入到最后元素处");
            System.out.println("\t\t  3--插入到某学号对应的元素处");
            System.out.println("\t\t  0--返回");
            System.out.println("\t\t--------------------------------");
            System.out.print("\t\t请选择(0 - 3)：");

            int option = scanner.nextInt();
            switch (option) {
                case 0:
                    return;
                case 1:
                    Student student = input();
                    insertion(arrayList, linkedList, student, 0);
                    System.out.println("\t\t插入到第1个元素处完成！");
                    break;
                case 2:
                    Student lastStudent = input();
                    insertion(arrayList, linkedList, lastStudent, arrayList.size() - 1);
                    System.out.println("\t\t插入到最后元素处完成！");
                    break;
                case 3:
                    System.out.print("\t\t插入位置对应的学号：");
                    int varSno = scanner.nextInt();
                    Student studentBySno = input();
                    insertBySno(arrayList, linkedList, studentBySno, varSno);
                    System.out.println("\t\t插入到某学号对应的元素处完成！");
                    break;
                default:
                    continue;
            }
        }
    }

    public static void menu7(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        // 实现对学生数组的特殊处理
    }

    public static Student input() {
        Scanner scanner = new Scanner(System.in);
        System.out.print("\t\t学号：");
        int sno = scanner.nextInt();
        scanner.nextLine(); // consume newline character
        System.out.print("\t\t姓名：");
        String sname = scanner.nextLine();
        System.out.print("\t\t性别：");
        String gender = scanner.nextLine();
        System.out.print("\t\t民族：");
        String nation = scanner.nextLine();
        System.out.print("\t\t年龄：");
        int age = scanner.nextInt();
        return new Student(sno, sname, gender, nation, age);
    }

    public static void inputAll(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        Scanner scanner = new Scanner(System.in);
        System.out.print("\n\t\t输入元素个数:");
        int count = scanner.nextInt();
        for (int i = 0; i < count; i++) {
            Student student = input();
            arrayList.add(student);
            linkedList.add(student);
        }
    }

    public static void output(Student student) {
        System.out.println("\n\t" + student.getSno() + "\t\t" + student.getSname() + "\t\t" +
                student.getGender() + "\t\t" + student.getNation() + "\t\t" + student.getAge());
    }

    public static void outputAll(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        System.out.println("\n\t学号\t\t姓名\t\t性别\t\t民族\t\t年龄");
        System.out.println("\t------------------------------------------");
        for (Student student : arrayList) {
            output(student);
        }
        System.out.println("\t------------------------------------------\n");
    }

    public static int computeByGender(ArrayList<Student> arrayList, LinkedList<Student> linkedList, String gender) {
        int count = 0;
        for (Student student : arrayList) {
            if (student.getGender().equalsIgnoreCase(gender)) {
                count++;
            }
        }
        for (Student student : linkedList) {
            if (student.getGender().equalsIgnoreCase(gender)) {
                count++;
            }
        }
        return count;
    }

    public static float computeAVG(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        int totalAge = 0;
        int count = 0;
        for (Student student : arrayList) {
            totalAge += student.getAge();
            count++;
        }
        for (Student student : linkedList) {
            totalAge += student.getAge();
            count++;
        }
        if (count == 0) return 0;
        return (float) totalAge / count;
    }

    public static void sortByAge(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        arrayList.sort((s1, s2) -> s1.getAge() - s2.getAge());
        linkedList.sort((s1, s2) -> s1.getAge() - s2.getAge());
    }

    public static void sortByNation(ArrayList<Student> arrayList, LinkedList<Student> linkedList) {
        arrayList.sort((s1, s2) -> s1.getNation().compareToIgnoreCase(s2.getNation()));
        linkedList.sort((s1, s2) -> s1.getNation().compareToIgnoreCase(s2.getNation()));
    }

    public static int findBySno(ArrayList<Student> arrayList, LinkedList<Student> linkedList, int sno) {
        for (int i = 0; i < arrayList.size(); i++) {
            if (arrayList.get(i).getSno() == sno) {
                return i;
            }
        }
        for (int i = 0; i < linkedList.size(); i++) {
            if (linkedList.get(i).getSno() == sno) {
                return i;
            }
        }
        return -1;
    }

    public static int deleteBySno(ArrayList<Student> arrayList, LinkedList<Student> linkedList, int sno) {
        int index = findBySno(arrayList, linkedList, sno);
        if (index != -1) {
            arrayList.remove(index);
            linkedList.remove(index);
        }
        return index;
    }

    public static void deletion(ArrayList<Student> arrayList, LinkedList<Student> linkedList, int index) {
        arrayList.remove(index);
        linkedList.remove(index);
    }

    public static void insertion(ArrayList<Student> arrayList, LinkedList<Student> linkedList, Student student, int index) {
        arrayList.add(index, student);
        linkedList.add(index, student);
    }

    public static void insertBySno(ArrayList<Student> arrayList, LinkedList<Student> linkedList, Student student, int sno) {
        int index = findBySno(arrayList, linkedList, sno);
        if (index != -1) {
            insertion(arrayList, linkedList, student, index);
        } else {
            System.out.println("\t\t学号不存在，插入失败！");
        }
    }

    public static void writeFile(ArrayList<Student> arrayList, LinkedList<Student> linkedList, String filename) {
        try {
            ObjectOutputStream outStream = new ObjectOutputStream(new FileOutputStream(filename));
            outStream.writeObject(arrayList);
            outStream.writeObject(linkedList);
            outStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void readFile(ArrayList<Student> arrayList, LinkedList<Student> linkedList, String filename) {
        try {
            ObjectInputStream inStream = new ObjectInputStream(new FileInputStream(filename));
            arrayList.addAll((ArrayList<Student>) inStream.readObject());
            linkedList.addAll((LinkedList<Student>) inStream.readObject());
            inStream.close();
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
